#include "compile.hpp"
#include "run.hpp"

#include <jsoncpp/json/json.h>
#include <boost/algorithm/string.hpp>

namespace ns_compile_run
{
    using namespace ns_compile;
    using namespace ns_run;

    class compile_run
    {
    public:
        static void DeleteTempFile(const std::string &filename,std::string language)
        {
            if (FileUtil::isFileExist(PathUtil::src(filename,language)))
            {
                unlink(PathUtil::src(filename,language).c_str());
            }
            if (FileUtil::isFileExist(PathUtil::exe(filename)))
            {
                unlink(PathUtil::exe(filename).c_str());
            }
            if (FileUtil::isFileExist(PathUtil::compileError(filename)))
            {
                unlink(PathUtil::compileError(filename).c_str());
            }
            if (FileUtil::isFileExist(PathUtil::stdcin(filename)))
            {
                unlink(PathUtil::stdcin(filename).c_str());
            }
            if (FileUtil::isFileExist(PathUtil::stdcout(filename)))
            {
                unlink(PathUtil::stdcout(filename).c_str());
            }
            if (FileUtil::isFileExist(PathUtil::stderror(filename)))
            {
                unlink(PathUtil::stderror(filename).c_str());
            }
        }
        /*
        输入型参数：
        给我一个json序列好的字符串:code:   input:
        先进行反序列化
        输出型参数：
        状态码 status
        状态码的说明 reason
        当运行正常的时候：stdcout   stderror
        */

        static std::string CauseOfStatus(int status, const std::string &filename)
        {
            // 6,24
            std::string reason;
            
            // Linux信号处理时，如果进程因信号而终止，退出状态码是信号编号加上128
            // 所以我们需要同时处理原始信号值和信号值+128的情况
            int signal_code = (status > 128) ? (status - 128) : status;
            
            switch (signal_code)
            {
            case 0:
                reason = "无错误";
                break;
            case -1:
                reason = "空代码";
                break;
            case -2:
                reason = "内部出现错误";
                break;
            case -3:
                FileUtil::ReadFile(PathUtil::compileError(filename), &reason, true);
                break;
            case SIGABRT:  // 6
                reason = "内存超限";
                break;
            case SIGXCPU:  // 24
                reason = "时间超限";
                break;
            case SIGFPE:   // 8
                reason = "浮点错误";
                break;
            case SIGSEGV:  // 11
                reason = "段错误";
                break;
            default:
                reason = "未知错误";
                break;
            }
            return reason;
        }

        static bool CompareOutput(const std::string &output, const std::string &expected_output)
        {
            std::vector<std::string> output_lines;
            std::vector<std::string> expected_lines;
            
            // 按行分割字符串
            FileSplit::SplitString(output, &output_lines, "\n");
            FileSplit::SplitString(expected_output, &expected_lines, "\n");
            
            // 如果最后一个元素是空字符串，则移除
            if (!output_lines.empty() && output_lines.back().empty()) {
                output_lines.pop_back();
            }
            if (!expected_lines.empty() && expected_lines.back().empty()) {
                expected_lines.pop_back();
            }
            
            int total_lines = std::max(output_lines.size(), expected_lines.size());
            int passed_lines = 0;
            
            // 逐行比较
            for (size_t i = 0; i < std::min(output_lines.size(), expected_lines.size()); i++)
            {
                boost::algorithm::trim(output_lines[i]);
                boost::algorithm::trim(expected_lines[i]);
                
                if (output_lines[i] == expected_lines[i])
                {
                    passed_lines++;
                }
            }
            
            // 计算通过率
            float pass_rate = (total_lines == 0) ? 100.0f : (static_cast<float>(passed_lines) / total_lines) * 100.0f;
            
            // 记录通过率
            LOG(INFO) << "测试通过率: " << pass_rate << "%" << std::endl;
            
            // 如果通过率大于等于100%，则认为完全通过
            return pass_rate >= 100.0f;
        }

        static void Start(const std::string &in_json, std::string *cout_json)
        {
            Json::Value in_value;
            Json::Reader reader;
            if (!reader.parse(in_json, in_value)) {
                LOG(ERROR) << "解析JSON失败: " << in_json << std::endl;
                Json::Value out_value;
                out_value["result_code"] = -2;
                out_value["reason"] = "解析JSON失败";
                Json::StyledWriter writer;
                *cout_json = writer.write(out_value);
                return;
            }

            // 提取信息
            std::string code = in_value["code"].asString();
            std::string input = in_value["input"].asString();
            std::string test_input = in_value["test_input"].asString();//测试输入
            std::string test_output = in_value["test_output"].asString();//测试输出
            std::string language = in_value["language"].asString();//编程语言
            int cpu = in_value["cpu"].asInt();
            int mem = in_value["mem"].asInt();

            LOG(INFO) << "收到编译请求: language=" << language << ", cpu=" << cpu << ", mem=" << mem << std::endl;
            LOG(INFO) << "代码长度: " << code.size() << std::endl;

            Json::Value out_value;
            
            // 处理空代码情况
            if (code.size() == 0)
            {
                LOG(ERROR) << "空代码" << std::endl;
                out_value["result_code"] = -1;
                out_value["reason"] = CauseOfStatus(-1, "");
                Json::StyledWriter writer;
                *cout_json = writer.write(out_value);
                return;
            }

            // 生成唯一的文件名——毫秒级时间戳加原子性递增
            std::string filename = FileUtil::UniqueName();
            LOG(INFO) << "生成文件名: " << filename << std::endl;

            // 把代码写入到文件中
            if (!FileUtil::WriteFile(PathUtil::src(filename,language), code))
            {
                LOG(ERROR) << "写入代码文件失败" << std::endl;
                out_value["result_code"] = -2;
                out_value["reason"] = CauseOfStatus(-2, filename);
                Json::StyledWriter writer;
                *cout_json = writer.write(out_value);
                DeleteTempFile(filename,language);
                return;
            }

            // 编译,运行——这里不要传加后缀的
            if (!Compile::compile(filename, language))
            {
                LOG(ERROR) << "编译失败" << std::endl;
                out_value["result_code"] = -3;
                out_value["reason"] = CauseOfStatus(-3, filename);
                Json::StyledWriter writer;
                *cout_json = writer.write(out_value);
                DeleteTempFile(filename,language);
                return;
            }

            // 分割测试用例
            std::vector<std::string> test_cases;
            FileSplit::SplitString(test_input, &test_cases, "\n\n");
            
            // 分割标准输出
            std::vector<std::string> expected_outputs;
            FileSplit::SplitString(test_output, &expected_outputs, "\n\n");
            
            // 移除最后一个空元素
            if (!test_cases.empty() && test_cases.back().empty()) {
                test_cases.pop_back();
            }
            if (!expected_outputs.empty() && expected_outputs.back().empty()) {
                expected_outputs.pop_back();
            }
            
            // 检查测试用例和标准输出的数量是否匹配
            if (test_cases.size() != expected_outputs.size()) {
                LOG(ERROR) << "测试用例和标准输出的数量不匹配" << std::endl;
                out_value["result_code"] = -2;
                out_value["reason"] = CauseOfStatus(-2, filename);
                Json::StyledWriter writer;
                *cout_json = writer.write(out_value);
                DeleteTempFile(filename,language);
                return;
            }
            
            // 运行每个测试用例
            int total_cases = test_cases.size();
            int passed_cases = 0;
            std::string error_case;
            
            for (size_t i = 0; i < test_cases.size(); i++) {
                // 写入当前测试用例
                if (!FileUtil::WriteFile(PathUtil::stdcin(filename), test_cases[i])) {
                    LOG(ERROR) << "写入测试用例失败" << std::endl;
                    out_value["result_code"] = -2;
                    out_value["reason"] = CauseOfStatus(-2, filename);
                    Json::StyledWriter writer;
                    *cout_json = writer.write(out_value);
                    DeleteTempFile(filename,language);
                    return;
                }
                
                // 运行程序
                int runRet = Run::run(filename, language, cpu, mem);
                LOG(INFO) << "运行返回值: " << runRet << std::endl;
                
                if (runRet < 0) {
                    LOG(ERROR) << "运行出错: " << runRet << std::endl;
                    out_value["result_code"] = -2;
                    out_value["reason"] = CauseOfStatus(-2, filename);
                    out_value["time"] = Run::GetLastRunTime();
                    out_value["memory"] = Run::GetLastRunMemory();
                    Json::StyledWriter writer;
                    *cout_json = writer.write(out_value);
                    DeleteTempFile(filename,language);
                    return;
                } else if (runRet > 0) {
                    LOG(INFO) << "程序异常退出，状态码: " << runRet << std::endl;
                    LOG(INFO) << "状态码解释: " << CauseOfStatus(runRet, filename) << std::endl;
                    
                    // 读取程序输出和错误信息
                    std::string _stdcout;
                    std::string _stderror;
                    FileUtil::ReadFile(PathUtil::stdcout(filename), &_stdcout, true);
                    FileUtil::ReadFile(PathUtil::stderror(filename), &_stderror, true);
                    
                    LOG(INFO) << "程序标准输出: " << _stdcout << std::endl;
                    LOG(INFO) << "程序错误输出: " << _stderror << std::endl;
                    LOG(INFO) << "运行时间: " << Run::GetLastRunTime() << std::endl;
                    LOG(INFO) << "内存使用: " << Run::GetLastRunMemory() << std::endl;
                    
                    out_value["result_code"] = runRet;
                    out_value["reason"] = CauseOfStatus(runRet, filename);
                    out_value["time"] = Run::GetLastRunTime();
                    out_value["memory"] = Run::GetLastRunMemory();
                    out_value["pass_rate"] = 0.0;  // 异常退出时通过率为0
                    out_value["output"] = _stdcout;
                    if (!_stderror.empty()) {
                        out_value["error"] = _stderror;
                    }
                    
                    // LOG(INFO) << "返回给前端的数据: " << std::endl;
                    Json::StyledWriter writer;
                    std::string response = writer.write(out_value);
                    LOG(INFO) << response << std::endl;
                    *cout_json = response;
                    DeleteTempFile(filename,language);
                    return;
                }
                
                // 读取程序输出
                std::string _stdcout;
                std::string _stderror;
                FileUtil::ReadFile(PathUtil::stdcout(filename), &_stdcout, true);
                FileUtil::ReadFile(PathUtil::stderror(filename), &_stderror, true);
                
                // 比较输出
                if (CompareOutput(_stdcout, expected_outputs[i])) {
                    passed_cases++;
                } else if (error_case.empty()) {
                    // 记录第一个错误的测试用例
                    error_case = "测试用例 " + std::to_string(i + 1) + ":\n";
                    error_case += "输入:\n" + test_cases[i] + "\n";
                    error_case += "期望输出:\n" + expected_outputs[i] + "\n";
                    error_case += "实际输出:\n" + _stdcout;
                }
            }
            
            // 计算通过率
            float pass_rate = (total_cases == 0) ? 100.0f : (static_cast<float>(passed_cases) / total_cases) * 100.0f;
            
            // 设置输出
            if (pass_rate == 100.0f) {
                out_value["result_code"] = 0;  // 完全通过
            } else {
                out_value["result_code"] = 1;  // 部分通过或完全不通过
            }
            out_value["pass_rate"] = pass_rate;
            out_value["output"] = "";  // 初始化输出字段
            
            // 读取最后一次运行的输出
            std::string _stdcout;
            std::string _stderror;
            FileUtil::ReadFile(PathUtil::stdcout(filename), &_stdcout, true);
            FileUtil::ReadFile(PathUtil::stderror(filename), &_stderror, true);
            
            // 设置输出和错误信息
            out_value["output"] = _stdcout;
            if (!_stderror.empty()) {
                out_value["error"] = _stderror;
            }
            
            // 添加运行时间和内存占用信息
            out_value["time"] = Run::GetLastRunTime();
            out_value["memory"] = Run::GetLastRunMemory();
            
            // 如果有错误用例，添加到结果中
            if (!error_case.empty()) {
                out_value["error_case"] = error_case;
            }
            
            // 序列化
            Json::StyledWriter writer;
            *cout_json = writer.write(out_value);
            LOG(INFO) << "返回结果: " << *cout_json << std::endl;

            // 清空临时文件
            DeleteTempFile(filename,language);
        }
    };
}